<template>
  <div
    :id="'chartMain' + chartId"
    v-loading="isVisualVappShowLoadingProgress && isLoading"
    class="chartMain horizontal-indicator"
    :class="`${componentStyleClass} ${componentStyle}-Style`"
  >
    <Tooltip ref="Tooltip" :component-style="componentStyle" />
    <AdvancedLinkageToolbar :wid="widgetInstanceId" :config="config" />
    <ComponentTitle ref="componentTitle" :property="config.config.property" :title-text-style="getCssStyle('title')" />
    <div
      class="displayBox"
      :style="{ height: title ? `calc(100% - ${titleHeight}px)` : '100%', ...getCssStyle('grid'), ...boxStyle }"
    >
      <div v-show="!isNoData && !isDataAbnormal" class="display-content">
        <div class="content-row">
          <div class="row0 row">
            <div :style="{ width: firstWidth, ...style.nameContent }">
              <span style="opacity:0;">123</span>
            </div>
            <div v-for="(item, index) in groupData" :key="index" :style="{ width: `${item.width}px` }">
              <div class="group" :style="style.group">
                <div v-if="getImg(item, index, 'title') || haveIcon(item.icon)" class="img" :style="style.imgDiv">
                  <Icon v-if="haveIcon(item.icon)" :conf="item.icon" />
                  <el-image v-else :src="getImg(item, index, 'title')" :style="style.elImage">
                    <template #placeholder>
                      <div class="image-slot">
                        {{ $demoi18n('message.loading') }}
                        <span class="dot">...</span>
                      </div>
                    </template>
                    <template #error>
                      <div></div>
                    </template>
                  </el-image>
                </div>
                <div class="text" :title="item.name" @click="emitOutGroupData(item, index)">
                  <span class="name" :style="{ ...style[componentStyle].group, ...getCssStyle('groupName') }">
                    {{ item.name }}
                  </span>
                </div>
              </div>
            </div>
          </div>
          <div v-for="(row, i) in configData" :key="i" :class="`row`">
            <div
              :style="{
                width: firstWidth,
                borderRight: `1px solid ${getValByCompStl('#ededed', '#1f415c', '#393939')}`,
              }"
            >
              <div class="name-content" :style="style.nameContent" :title="`${row.name}${row.unit || ''}`">
                <span
                  v-show="row.name.length > 0"
                  class="name"
                  :style="{ ...style[componentStyle].name, ...getCssStyle('indexName') }"
                >
                  {{ `${row.name} ` }}
                </span>
                <span :style="{ ...style[componentStyle].unit, ...getCssStyle('unit') }">{{ row.unit }}</span>
              </div>
            </div>
            <div
              v-for="(item, index) in groupData"
              :key="index"
              v-visual-tooltip="getTooltip(item)"
              :style="{ width: `${item.width}px`, overflow: 'hidden' }"
              @click="emitOutData(item, i, index)"
            >
              <div class="content" :style="style.nameContent" :title="item.children[i]">
                <span class="value" :style="{ ...style[componentStyle].value, ...getCssStyle('value') }">
                  {{ item.children[i] }}
                </span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <NoData
        :isNoData="isNoData"
        :boxBgColor="boxBgColor"
        :noDataPromptType="config.config.property.noDataPromptType"
        :noDataPrompt="config.config.property.noDataPrompt"
      />
      <AbnormalData :isDataAbnormal="isDataAbnormal" :boxBgColor="boxBgColor" :abnormalType="abnormalType" />
    </div>
  </div>
</template>
<script>
import AdvancedLinkageToolbar from '@/components/common/advanced-linkage/advanced-linkage-toolbar.vue';
import Icon from '@/components/common/icon/icon.vue';
import chartBase from '@/mixin/chart-base.js';
import componentValueBase from '@/mixin/component-value-base.js';
import iconChartBase from '@/mixin/icon-chart-base.js';
import dataModel from '@/models/panel-config-data.js';
import { numFormat } from '@/utils/util';
import { getCommonVal } from '@/utils/util-common.js';
import { convertValue } from '@/utils/util.js';
import { nextTick } from 'vue';
import ComponentTitle from '../common/component-title/component-title.vue';
import NoData from '../common/no-data/no-data.vue';
import AbnormalData from '../common/abnormal-data/abnormal-data.vue';
import Tooltip from '../common/tooltip/tooltip.vue';
import colorGroup from './config/colorGroup';
import config from './config/config';
import dfCssStyle from './config/cssStyle-default.js';

export default {
  name: 'HorizontalIndicatorChart',
  components: { ComponentTitle, NoData, Tooltip, Icon, AbnormalData, AdvancedLinkageToolbar },
  mixins: [chartBase, iconChartBase, componentValueBase],
  props: ['pareentId', 'widgetId', 'widgetInstanceId', 'widgetName', 'identifier', 'layout', 'w', 'h'],
  data() {
    return {
      isLoading: false,
      isNoData: false,
      orgConfig: [],
      isShow: true,
      chartId: '',
      config: null,
      title: '',
      groupData: [],
      configData: [],
      apiResult: [],
      dataCount: 0,
      groupCount: 0,
      style: {
        light: {
          box: { backgroundColor: '#FFF', borderTop: '' },
          back: { backgroundColor: '#F5FAFF' },
          value: { color: '#00AAFF' },
          group: { color: '#666666' },
          name: { color: '#666666' },
          unit: { color: '#666666' },
          title: { color: '#3C3C3C' },
        },
        dark: {
          box: { backgroundColor: '#0D263A', borderTop: '' },
          back: { backgroundColor: '#122E45' },
          value: { color: '#ffffff' },
          group: { color: '#ffffff' },
          name: { color: '#adc5d9' },
          unit: { color: '#ffffff' },
          title: { color: '#00f7ff' },
        },
        real: {
          box: { backgroundColor: '#0D263A', borderTop: '' },
          back: { backgroundColor: '#122E45' },
          value: { color: '#ffffff' },
          group: { color: '#ffffff' },
          name: { color: '#adc5d9' },
          unit: { color: '#ffffff' },
          title: { color: '#00f7ff' },
        },
        group: {},
        imgDiv: {},
        elImage: {},
        nameContent: {},
      },
      componentStyle: window._adoPremise.uc.theme,
      colorGroup: colorGroup,
      firstWidth: 0,
      titleHeight: 0,
      row0Hieght: 0,
      row0Width: 0,
      boxStyle: {},
      dfCssStyle,
    };
  },
  computed: {
    spanWidth: {
      get() {
        return parseInt(24 / (this.groupCount + 1));
      },
    },
  },
  watch: {
    w() {
      this.updateComponentByResolution();
    },
    h() {
      this.updateComponentByResolution();
    },
  },
  created() {
    this.orgConfig = config;
    this.config = JSON.parse(JSON.stringify(this.orgConfig));
    this.chartId = `${this.widgetInstanceId}_01`;
  },
  mounted() {
    if (window.isLocalEnv) {
      this.loadWidget();
    }
  },
  methods: {

    // 初始加载时 以及 编排面更改配置时 触发
    loadWidget(pageStatus) {
      this.componentStyle = this.config.config.property.componentStyle || 'light';
      this.pageStatus = pageStatus;
      this.updateImgUrlHorizontalIndicator();
      this._updateConfigProperty();

      this.updateConfigData();

      this.updateComponentByResolution();

      if (window.isLocalEnv || this.emitComponentStatus) {
        this.updateParams(pageStatus);
        if (!this.isRealTime) {
          this.debounceGetData();
        }
      }
      this.afterLoadWidget();
    },
    emitOutData(item, rowIndex, colIndex) {
      const obj = {
        series: item.name,
        name: this.configData[rowIndex].name,
        value: item.children[rowIndex] + this.configData[rowIndex].unit,
      };
      const { paramKey } = this.config.events[0]; // 字段名code
      const { tableData } = this.config.config.data;
      const col = tableData.find(t => String(t.mapping) === String(paramKey));
      this.executeAction('', item);
      if ((col && col.field === 's') || String(paramKey) === String(tableData[rowIndex + 1].mapping)) {
        this.sendAllMessages(obj, `${rowIndex}|${colIndex}`);
      }
      if (item) {
        this.sendAdvancedLinkagge({ s: item.name, y1: item.children[0], y2: item.children[1] });
      }
    },
    emitOutGroupData(item, rowIndex) {
      const obj = {};
      const { paramKey } = this.config.events[0]; // 字段名code
      const { tableData } = this.config.config.data;
      const col = tableData.find(t => String(t.mapping) === String(paramKey));
      this.executeAction('', item);
      if (col && col.field === 's') {
        obj.series = item.name;
      }
    },
    getImg(item, index, img = 'content') {
      const imgNum = 2;
      if (item.imgUrl) {
        return item.imgUrl;
      }
      return '';
    },

    // 根据分辨率来更新组件
    updateComponentByResolution() {
      const { group, imgSize = 26 } = this.config.config.property;
      const { property } = this.config.config;
      this.updateGroupDataResolution(group);

      this.updateChartFontSize();
      nextTick(() => {
        this.style.group.padding = `${convertValue(10)}px`;
        this.style.imgDiv.marginRight = `${convertValue(5)}px`;
        this.style.elImage.width = `${convertValue(imgSize)}px`;
        this.style.elImage.height = `${convertValue(imgSize)}px`;
        this.style.nameContent.padding = `${convertValue(8, 0)}px`;
        this.style = JSON.parse(JSON.stringify(this.style));
        if (property.backgroundColor) {
          this.boxStyle.backgroundColor = `${property.backgroundColor}!important`;
        } else {
          this.boxStyle.backgroundColor = `${getCommonVal('boxBgColor', property.componentStyle)}!important`;
        }
        setTimeout(() => {
          const title = document.querySelector(`#chartMain${this.chartId} .component-title`);
          const row0 = document.querySelector(`#chartMain${this.chartId} .row0`);
          this.titleHeight = title ? title.offsetHeight : 0;
          this.row0Hieght = row0 ? row0.offsetHeight : 0;
        }, 10);
      });
    },
    _updateConfigProperty() {
      this.updateConfigProperty();
      const { group, data } = this.config.config.property;
      this.dataCount = data.length;
      this.groupCount = group.length;
      this.updateGroupData(group);
      const newArr = data.map(item => {
        if (item.unit) {
          item.unit = `/${item.unit}`;
          return item;
        } else {
          return item;
        }
      });
      this.configData = newArr;
      this.updateChartValueStyle();
    },
    updateGroupData(groups) {
      let totalWidth = 0;
      const configGroupData = JSON.parse(JSON.stringify(groups));
      configGroupData.forEach(group => {
        let width;
        if (!group.width) {
          width = convertValue(120);
        } else {
          width = convertValue(group.width, 60); // 设置最小值不能每次都压缩
        }
        group.width = width;
        totalWidth += group.width;
      });
      this.firstWidth = `calc(100% - ${totalWidth}px)`;
      this.groupData = configGroupData;
    },
    updateGroupDataResolution(groups) {
      let totalWidth = 0;
      const configGroupData = JSON.parse(JSON.stringify(groups));
      this.groupData.forEach(group => {
        const configGroupItem = configGroupData.find(item => item.name === group.name);
        if (configGroupItem) {
          group.width = convertValue(configGroupItem.width || 120, 60);
          totalWidth += group.width;
        }
      });
      this.firstWidth = `calc(100% - ${totalWidth}px)`;
    },

    clearGroupData() {
      for (let i = 0; i < this.groupCount; i++) {
        this.groupData[i].children = [];
      }
    },
    updateChartFontSize() {
      const { fontSizeName, fontSizeValue } = this.config.config.property;
      nextTick(() => {
        this.style[this.componentStyle].name.fontSize = `${convertValue(fontSizeValue, 12)}px`;
        this.style[this.componentStyle].unit.fontSize = `${convertValue(fontSizeValue, 12)}px`;
        this.style[this.componentStyle].value.fontSize = `${convertValue(fontSizeValue, 12)}px`;
        this.style[this.componentStyle].group.fontSize = `${convertValue(fontSizeName, 12)}px`;
        this.style = JSON.parse(JSON.stringify(this.style));
      });
    },
    updateChartValueStyle() {
      const { componentStyle, fontColor, propertyGroup } = this.config.config.property;
      nextTick(() => {
        if (!fontColor || fontColor.indexOf('#') === 0) {
          this.style[componentStyle].value.color = fontColor;
          this.style[componentStyle].unit.color = fontColor;
        } else {
          // multiSingle1 兼容旧的颜色选项设置
          this.style[componentStyle].value.color = this.colorGroup[componentStyle][propertyGroup][fontColor][0];
          this.style[componentStyle].unit.color = this.colorGroup[componentStyle][propertyGroup][fontColor][0];
        }
      });
    },
    handleValueResult(result) {
      this.apiResult = [];
      for (let i = 0; i < this.groupCount; i++) {
        const element = result.find(item => item.s === this.groupData[i].name);
        if (element) {
          this.apiResult.push(element);
          for (let j = 0; j < this.dataCount; j++) {
            this.groupData[i].children.push(numFormat(element[`y${j + 1}`], true));
            this.groupData[i].orgData = element;
          }
        }
      }
    },
    handleRealTimeCommunication(realTimeData) {
      if (this.config.config.property.isDebounce && this.isStopRealData) {
        return;
      }

      const result = this.getResult(realTimeData);
      if (this.isNoData || this.autoRefreshIsSameRes(result)) {
        this.isLoading = false;
        return;
      }
      this.handleValueResult(result);
      this.isLoading = false;
    },

    // api请求获取图表数据
    getChartData() {
      const { data } = this.config.config;

      // 如果dataSourceType为静态数据,把数据放到Vuex，发出事件，然后退出
      if (data.dataSourceType === 'staticData') {
        const result = this.getStaticData();
        this.sendDataToConfig(result);
        if (result && result.length) {
          this.handleValueResult(result);
        }
        this.isNoData = !result.length;

        // 重置数据异常状态
        this.resetAbnormalType();
        return;
      }

      // api请求，拿到数据
      if (data.dataSourceType) {
        this.isLoading = true;
        this.isNoData = false;
        this.autoRefresh();
        const method = `getChartData${data.dataSourceType}`;
        const params = this.getCorrectParams(this.params, data.dataSourceType);
        dataModel[method](params, data)
          .then(result => {
            // 重置数据异常状态
            this.resetAbnormalType();
            this.reportIfFieldsError(this.getParams()?.propertyMapping, result);
            if (this.autoRefreshIsSameRes(result)) {
              return;
            }
            this.clearGroupData();
            this.sendDataToConfig(result);

            if (result && result.length) {
              this.handleValueResult(result);
            }
            this.isNoData = !result.length;
          })
          .catch(err => {
            this.handleChartDataError(err);
          })
          .finally(() => {
            this.isLoading = false;
          });
      } else {
        // 如果在用户面，则给提示
        if (this.$route.name === 'userHomePage') {
          this.$message({
            message: this.$demoi18n('view.dataSourceTypeEmpty'),
            type: 'warning',
          });
        }
      }
    },
    getTooltip(item) {
      const { tableData } = this.config.config.data;
      const vars = { s: item.name };
      tableData.forEach((n, i) => {
        if (n.field === 's') {
          vars.s = item.name;
        } else {
          vars[n.field] = item.children[i - 1];
        }
      });

      return {
        config: this.config.config.property.tooltip || {},
        vars,
        params: this.params,
        parentComp: this,
      };
    },
  },
};
</script>
<style lang="less" scoped>
// 图表通用样式，主要有黑色loading 和 黑色 ‘没有数据’，样式名需一致
@import '../../common/chart.less';
</style>
<style lang="less" scoped>
@import './config/theme.less';
.horizontal-indicator {
  .title {
    width: 100%;
    height: 50px;
    font-size: 18px;
    position: relative;
    span {
      display: flex;
      align-items: center;
      height: 100%;
      margin-left: 5%;
    }
  }
  .displayBox {
    width: 100%;

    overflow-y: hidden;
    margin: 0 auto;
    text-align: center;
    .display-content {
      width: 100%;
      height: 100%;
      overflow: auto;
      .row {
        display: flex;
        flex: 1;
      }

      .row0 {
        > div {
          border-bottom: 1px solid var(--row0-border-color);
        }
        .group {
          padding: 10px;
          display: flex;
          justify-content: center;
          align-items: center;
          height: 100%;
          .img {
            margin-right: 5px;
            display: flex;
            justify-content: center;
            align-items: center;
            .el-image,
            .image-slot {
              width: 26px;
              height: 26px;
              vertical-align: middle;
            }
          }
          .text {
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
          }
        }
      }
      .content-row {
        overflow: visible;
        width: max-content;
        min-width: 100%;
        display: flex;
        flex-direction: column;
        height: 100%;
        .name-content {
          text-align: right;
          padding: 8px;
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          border: var(--name-content-border) !important;
        }
        .content {
          text-overflow: ellipsis;
          overflow: hidden;
          white-space: nowrap;
          .value {
          }
        }
      }
    }
  }
}
</style>
